#! /usr/bin/python2.7

import os, os.path, sys, time, select, signal, json

PPS_CONTROLLER = "/pps/services/cds/cnice/update?wait";

DEBUG = False;

def ppscall(fd, msg, id, dat = None):
	if fd < 0:
		return (-1, "invalid PPS fd");
	if msg is None or len(msg) == 0:
		return (-2, "invalid message type");
	if id is None or len(id) == 0:
		return (-3, "invalid message id");
	
	req = 'msg::{0}\nid::{1}\n'.format(msg, id);
	if not dat is None:
		req += '{0}\n'.format(dat);
	
	if DEBUG:
		print req;
	
	os.write(fd, req);
	resp = os.read(fd, 4 * 1024);
	
	if DEBUG:
		print resp;
	
	errcode = 0;
	reply = "";
	for line in resp.split("\n"):
		if len(line) > 0:
			if line.startswith("dat:json:"):
				reply = line[len("dat:json:"):];
			elif line.startswith("dat::"):
				reply = line[len("dat::"):];
			if line.startswith("err:n:"):
				errcode = int(line[len("err:n:"):]);
	return (errcode, reply);

def newsession(fd):
	(errcode, reply) = ppscall(fd, 'session_begin', 'session_begin_user_1');
	if errcode != 0:
		print "newsession() failed, errcode = {0}\n".format(errcode);
		return -1;
	
	decoder = json.JSONDecoder();
	attribs = decoder.decode(reply);
	if "sessionid" in attribs:
		return int(attribs["sessionid"]);
	
	print "newsession() session_id is not returned\n";
	return -1;

def endsession(fd, sessionid):
	(errcode, reply) = ppscall(fd, 'session_commit', 'session_commit_user_1', 
							'dat:json:{{"sessionid":{0}}}'.format(sessionid));
	if errcode != 0:
		print "endsession() failed, errcode = {0}\n".format(errcode);
	else:
		print "endsession() close session {0}\n".format(sessionid);

def cancelsession(fd, sessionid):
	(errcode, reply) = ppscall(fd, 'session_rollback', 'session_rollback_user_1', 
							'dat:json:{{"sessionid":{0}}}'.format(sessionid));
	if errcode != 0:
		print "cancelsession() failed, errcode = {0}\n".format(errcode);
	else:
		print "cancelsession() close session {0}\n".format(sessionid);

def update(fd, sessionid, msg, svcname, dat = None):
	if dat is None: 
		(errcode, reply) = ppscall(fd, '{0}'.format(msg), 'update_ex_user_1',
								'dat:json:{{"sessionid":{0}, "name":"{1}"}}'.format(sessionid, svcname));
	else:
		(errcode, reply) = ppscall(fd, '{0}'.format(msg), 'update_ex_user_1',
								'dat:json:{{"sessionid":{0}, "name":"{1}", {2}}}'.format(sessionid, svcname, dat));
	if errcode != 0:
		print "update() failed, errcode = {0}\n".format(errcode);
	else:
		print "update() succeeded\n";
		
	return errcode;

def query(fd, msg, svcname, dat):
	(errcode, reply) = ppscall(fd, '{0}'.format(msg), 'query_user_1',
							'dat:json:{{"name":"{0}", {1}}}'.format(svcname, dat));
	if errcode != 0:
		print "query() failed, errcode = {0}\n".format(errcode);
	else:
		print "{0}\n".format(reply);
	
	return errcode;

def call_update(pps, commands):
	if len(commands) == 0:
		print "no commands to execute\n";
		return;
	
	fd = os.open(pps, os.O_RDWR);
	
	sessionid = newsession(fd);
	print "session id = {0}\n".format(sessionid);
	if sessionid == -1:	
		return;
	
	errcode = 0;
	for command in commands:
		args = command.split(";");
		if len(args) < 2:
			continue;
		
		msg = args[0].strip();
		if msg == "update" or msg == "reset":		
			if len(args) == 2:
				errcode = update(fd, sessionid, msg, args[1].strip());
			elif len(args) == 3:
				errcode = update(fd, sessionid, msg, args[1].strip(), args[2].strip());
			else:
				print "'{0}' has invalid parameters\n".format(command);
		elif msg == "query":
			if len(args) == 3:
				errcode = query(fd, msg, args[1].strip(), args[2].strip());
			else:
				print "'{0}' has invalid parameters\n".format(command);
		else:
			print "'{0}' is not supported\n".format(command);

		if errcode != 0:
			break;
	
	if errcode == 0:
		endsession(fd, sessionid);
	else:
		cancelsession(fd, sessionid);
	
	os.close(fd);


def main():
	if len(sys.argv) < 2:
		print "Usage: {0} <command|commandFile>".format(sys.argv[0]);
		exit;
	
	commands = [];
	
	if sys.argv[1].find(";") != -1:
		commands.append(sys.argv[1]);
	else:
		with open(sys.argv[1]) as fin:
			for line in fin:
				if line.startswith("#"):
					continue;
				
				if len(line.strip()) > 0 :
					commands.append(line.strip());

	if len(commands) == 0:
		print "{0} does not contain valid commands\n".format(sys.argv[1]);
		exit;

	call_update(PPS_CONTROLLER, commands);
		
if __name__ == "__main__":
	main();